package cn.smile.utils;

import cn.smile.commons.constant.NumberConstant;
import cn.smile.commons.enums.basic.MiniProjectCountEnum;
import cn.smile.commons.exceptions.BusinessException;
import cn.smile.commons.response.MyResponseCode;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

/**
 * @author smile-jt
 */
@Slf4j
public class DateFormatUtil {

    /**
     * 日期格式，年月日时分秒，年月日用横杠分开，时分秒用冒号分开
     * 例如：2005-05-10 23：20：00，2008-08-08 20:08:08
     */
    public static final String DATE_TIME_FORMAT_1 = "yyyy-MM-dd HH:mm:ss";
    public static final String DATE_TIME_FORMAT_2 = "yyyy/MM/dd";
    public static final String DATE_TIME_FORMAT_3 = "HH:mm";
    public static final String DATE_TIME_FORMAT_7 = "yyyy年MM月dd日";
    public static final String TO_DATE_START = "yyyy-MM-dd 00:00:00";
    public static final String TO_DATE_END = "yyyy-MM-dd 23:59:59";


    /**
     * LocalDateTime转Date
     *
     * @param localDateTime 待转换的时间
     * @return 转换后的时间
     */
    @SuppressWarnings("unused")
    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * LocalDate转Date
     *
     * @param localDate 待转换的时间
     * @return 转换后的时间
     */
    public static Date localDateToDate(LocalDate localDate) {
        return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 格式化Date时间
     *
     * @param time       Date类型时间
     * @param timeFormat String类型格式
     * @return 格式化后的字符串
     */
    public static String parseDateToStr(Date time, String timeFormat) {
        DateFormat dateFormat = new SimpleDateFormat(timeFormat);
        return dateFormat.format(time);
    }

    /**
     * 字符串转时间格式
     *
     * @param time       待转换的字符串
     * @param timeFormat 时间格式
     * @return 转换后的Date时间
     */
    public static Date parseStrToDate(String time, String timeFormat) {
        DateFormat dateFormat = new SimpleDateFormat(timeFormat);
        Date resultTime;
        try {
            resultTime = dateFormat.parse(time);
        } catch (Exception e) {
            log.error("字符串转时间异常, e: ", e);
            throw new BusinessException(MyResponseCode.STRING_TO_DATETIME_ERROR);
        }
        return resultTime;
    }

    /**
     * 指定时间累加天数
     *
     * @param date   指定时间
     * @param amount 累加量
     * @return 计算结果时间
     */
    public static Date addDays(Date date, int amount) {
        return add(date, Calendar.DAY_OF_MONTH, amount);
    }

    @SuppressWarnings({"SameParameterValue", "MagicConstant"})
    private static Date add(final Date date, final int calendarField, final int amount) {
        if (ObjectUtils.isEmpty(date)) {
            throw new BusinessException(MyResponseCode.COUNT_DATE_ERROR);
        }
        final Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(calendarField, amount);
        return c.getTime();
    }

    /**
     * 根据统计范围获取统计开始时间
     *
     * @param date      计算截止时间
     * @param countEnum 统计范围
     * @return 计算结果时间字符串
     */
    public static String getCountStartTime(Date date, MiniProjectCountEnum countEnum) {
        String startTime;
        switch (countEnum) {
            case TODAY:
                break;
            case LAST_SEVEN_DAYS:
                date = addDays(date, NumberConstant.MINUS_SEVEN);
                break;
            default:
        }
        startTime = parseDateToStr(date, DateFormatUtil.TO_DATE_START);
        return startTime;
    }

    /**
     * 获取最近7天的日期
     *
     * @return 获取结果数组
     */
    public static List<String> getRecentDays() {
        List<String> days = Lists.newArrayList();
        Date nowTime = new Date();
        for (int i = 0; i < NumberConstant.SEVEN; i++) {
            days.add(String.format("%s日", parseDateToStr(addDays(nowTime, -i), "dd")));
        }
        Collections.reverse(days);
        return days;
    }

    /**
     * 获取指定时间月份的最后一天
     *
     * @param date 指定时间
     * @return 最后一天时间
     */
    public static Date getLastDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int lastDay = calendar.getActualMaximum(Calendar.DATE);
        calendar.set(Calendar.DAY_OF_MONTH, lastDay);

        return calendar.getTime();
    }
}
